package com.topfox.common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.topfox.annotation.Ignore;
//import com.topfox.misc.JsonUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Type;
import java.util.*;

@JsonInclude(JsonInclude.Include.NON_EMPTY)
@Setter
@Getter
@Accessors(chain = true)
public class Response<T> {
    @JsonIgnore @Ignore transient Logger logger= LoggerFactory.getLogger(getClass());

    /**
     * 是否成功
     */
    private boolean success;

    /**
     * 异常编码
     */
    private String code;

    /**
     * 详细信息
     */
    private String msg;

    /**
     * 前端(请求方)每次请求传入的 唯一 执行Id, 如果没有, 后端会自动生成一个唯一的
     */
    private String executeId;

    /**
     * 1.查询结果的所有页的行数合计,
     * 2.update insert delete SQL执行结果影响的记录数
     */
    private Integer totalCount;


    /**
     * 查询结果(当前页)的行数合计
     */
    private Integer pageCount;

    /**
     * 数据, List<UserDTO> 或者是一个DTO
     */
    @JsonSerialize(using = ListJsonSerialize.class)
    private T data;


    /**
     * data 泛型 T 的实际类型
     */
    @JsonIgnore
    Type dataType;
    public Type getDataType() {
        if (dataType == null && data != null) {
            dataType = data.getClass();
        }
        return dataType;
    }
    public void setDataType(Type dataType) {
        if (this.dataType == null) {
            this.dataType = dataType;
        }
    }
    /**
     * 异常类名
     */
    private String exception;

    /**
     * 方法
     */
    private String method;

    private JSONObject attributes = new JSONObject();

    public Response() {
        super();//spring cloud 序列化必须


    }

    public Response(String code, String msg) {
        this.code = code;
        this.msg = msg;
        this.success = ResponseCode.SUCCESS.getCode().equals(code);
    }

    public Response(ResponseCode responseCode) {
        this(responseCode.getCode(), responseCode.getMsg());
    }

    public Response(ResponseCode responseCode, String msg) {
        this(responseCode.getCode(), msg);
    }

    public Response(Throwable e, ResponseCode responseCode) {
        this.code = responseCode.getCode();
        this.msg = responseCode.getMsg();
        setError(e);
        logger.warn(" ResponseError >>> Exception:{} Method:{}", this.exception, this.method);
    }
    public Response(Throwable e, ResponseCode responseCode, String msg) {
        this.code = responseCode.getCode();
        this.msg = msg;
        setError(e);
        logger.warn(" ResponseError >>> Exception:{} Method:{}", this.exception, this.method);
    }
    public Response(Throwable e) {
        this.code = ResponseCode.SYSTEM_ERROR.getCode();
        this.msg = e.getMessage();
        setError(e);
        logger.warn(" ResponseError >>> Exception:{} Method:{}", this.exception, this.method);
    }

    public Response(T data) {
        this(ResponseCode.SUCCESS);
        this.data = data;
        if (data != null) {
            dataType = data.getClass();
            if (data instanceof Collection) {
                this.totalCount = ((Collection) data).size();
            }else {
                this.totalCount = 1;
            }
        } else {
            this.totalCount = 0;
        }
    }

    /**
     *
     * @param data
     * @param totalCount 查询时 为 所有页的行数,  插入 更新 删除时, 为SQL执行成功所影响记录的行数
     */
    public Response(T data, Integer totalCount) {
        this(ResponseCode.SUCCESS);
        this.data = data;
        this.totalCount = totalCount;

        if (data != null) {
            dataType = data.getClass();
            if (data instanceof Collection) {
                this.pageCount = ((Collection) data).size();//当前页的行数
            } else {
                this.totalCount = 1;
            }
        } else {
            this.totalCount = 0;
        }
    }

    protected void setError(Throwable e){
        success = false;
        msg = msg==null?"":msg;

        if (e instanceof TopException){
            TopException ex = (TopException)e;
            this.code = ex.getCode();
            int pos = msg.lastIndexOf("]\n\r");
            if (pos > 0 ) {
                msg = msg.substring(pos + 3);
            }
        }
        this.exception=e.getCause()!=null?e.getCause().getClass().getName():e.getClass().getName();

        //打印异常信息及处理; 对 Response.method赋值
        ExceptionBuilder.printStackTrace(e, this);
    }

//    public String toString(){
//        String temp= JsonUtil.toString(this);
//        return "执行结果 "+ (temp.length()>500?temp.substring(0,500):temp);
//    }

    public String toJSONString(){
        return JSON.toJSONString(this);
    }
}
